/* Copyright (c) 2009 SpringShowcase, Inc.
 * All right reserved.
 * http://code.google.com/p/springshowcase/
 * This software is the confidential and proprietary information of BeyondWeb
 * , Inc. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license agreement
 * you entered into with BeyondWeb.
 *
 * Revision History
 * Author              Date             Description
 * ------------------   --------------    ------------------
 *  taeki.kim           2010. 4. 2.        
*/

package org.springshowcase.core.commons.logs;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.IterableMap;
import org.apache.commons.collections.MapIterator;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 시스템에서 사용하는 properties 파일의 내용을 공 유 메모리로 관리
 * 
 * InitConfigProperties클래스로 선언된 스프링 빈이 WAS 기동시 service.properties
 * 내용의 값을 메모리로 로드 된다. 시스템에서 참조시 ConfigProperties.getXXX(메세지 키)메서드를
 * 리턴 타입에 맞게 호출 하면 된다.
 * 
 * @author kim.tae.ki
 * @version
 * @see
 * 
 * This file contains the declarations of String class and its helper classes.
 */
public class HttpLoggingInterceptor extends HandlerInterceptorAdapter {

    // ---------------------------------------------------------------------
    // Class Variable Declaration
    // ---------------------------------------------------------------------
    
    /** 클래스에서 사용하는 로거. */
	private static final Logger logger = LoggerFactory
			.getLogger(HttpLoggingInterceptor.class);

	// ---------------------------------------------------------------------
    // Constructor Method Declaration
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // DI Method (setter,getter) Declaration
    // ---------------------------------------------------------------------

    // ---------------------------------------------------------------------
    // this Method (public/private) Declaration
    // ---------------------------------------------------------------------	

	/**
	 * AOP Target 메서드 후 실행
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView)
	 */
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		super.postHandle(request, response, handler, modelAndView);
	}

	/**
	 * AOP Target 메서드 전 실행
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		StringBuffer sbAppender = new StringBuffer();
		String strKey;
		String[] strValues;
		IterableMap iterableMap;
		MapIterator mapIterator;
		if (logger.isInfoEnabled()) {
			request
					.setAttribute("WEB_EXECUTE_TIME",new Long(System
							.currentTimeMillis()));
			sbAppender
			.append(
			"\n=Invoke Request===========================================")
					.append(
							"\nⓒ\n")
					.append(
							" Request URL : [" + request.getRequestURI()
									+ "]\n").append(
							" Client Addr : [" + request.getRemoteHost()
									+ "(IP:" + request.getRemoteAddr() + ")"
									+ "]\n").append(" UserId : [" + "]\n")
					.append(
							" Request Method Type : [" + request.getMethod()
									+ "]\n").append(
							" Request Encoding : ["
									+ request.getCharacterEncoding() + "]\n");
			if (!ServletFileUpload.isMultipartContent(request)) {
			    sbAppender.append(" Request Parameters : [");
			    iterableMap = new HashedMap(request.getParameterMap());
			    mapIterator = iterableMap.mapIterator();
				while (mapIterator.hasNext()) {
				    strKey = (String) mapIterator.next();
				    strValues = (String[]) mapIterator.getValue();
					sbAppender.append(strKey + "=").append(
							ArrayUtils.toString(strValues) + ",");
				}
				sbAppender.append("]\n");
			}
			if (logger.isInfoEnabled()) {
			    logger.info(sbAppender.toString());
			}
		}
		return super.preHandle(request, response, handler);
	}

	/**
     * AOP Target 메서드가 성공적으로 처리 된 후 실행
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 */
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		StringBuffer sbAppender = new StringBuffer();
		if (logger.isInfoEnabled()) {
		    sbAppender
					.append(
							"\n Controller Execution time : ["
									+ (System.currentTimeMillis() - ((Long) request
											.getAttribute("WEB_EXECUTE_TIME")).longValue())
									+ " ms]\n");
		
			if (logger.isInfoEnabled()) {
			    logger.info(sbAppender.toString());
			}
		}
		super.afterCompletion(request, response, handler, ex);
	}
	
	// ---------------------------------------------------------------------
    // interface implement Method (public/private) Declaration
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // abstract implement Method (public/private) Declaration
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // abstract Method (public/private) Declaration
    // ---------------------------------------------------------------------
	
}
